package com.foxsteps.gsonformat.ui;

import com.foxsteps.gsonformat.Constants;
import com.foxsteps.gsonformat.ConvertBridge;
import com.foxsteps.gsonformat.common.JsonUtils;
import com.foxsteps.gsonformat.config.Config;
import com.foxsteps.gsonformat.tools.json.JSONArray;
import com.foxsteps.gsonformat.tools.json.JSONException;
import com.foxsteps.gsonformat.tools.json.JSONObject;
import com.foxsteps.gsonformat.utils.ToStringUtils;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.PsiJavaFileImpl;
import org.apache.http.util.TextUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class JsonDialog extends JFrame implements ConvertBridge.Operator {

    private CardLayout cardLayout;

    private JPanel contentPane2;
    private JButton okButton;
    private JButton cancelButton;
    private JLabel errorLB;
    private JTextArea editTP;

    private JLabel generateClassLB;
    private JTextField generateClassTF;
    private JPanel generateClassP;
    private JTextArea commentAR;

    private PsiClass cls;
    private PsiFile file;
    private Project project;
    private String errorInfo = null;
    private String currentClass = null;

    public JsonDialog(PsiClass cls, PsiFile file, Project project) throws HeadlessException {
        this.cls = cls;
        this.file = file;
        this.project = project;
        //设置内容面板
        setContentPane(contentPane2);
        setTitle("ToStringToJson");
        getRootPane().setDefaultButton(okButton);
        this.setAlwaysOnTop(true);
        //初始化面板
        initGeneratePanel(file);
        //初始化监听器
        initListener();
    }

    private void initGeneratePanel(PsiFile file) {

        cardLayout = (CardLayout) generateClassP.getLayout();
        generateClassTF.setBackground(errorLB.getBackground());
        //获取当前Class
        currentClass = ((PsiJavaFileImpl) file).getPackageName() + "." + file.getName().split("\\.")[0];
        generateClassLB.setText(currentClass);
        generateClassTF.setText(currentClass);
        //生成类输入框焦点监听器
        generateClassTF.addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent focusEvent) {
            }

            @Override
            public void focusLost(FocusEvent focusEvent) {
                cardLayout.next(generateClassP);
                if (TextUtils.isEmpty(generateClassTF.getText())) {
                    generateClassLB.setText(currentClass);
                    generateClassTF.setText(currentClass);
                } else {
                    generateClassLB.setText(generateClassTF.getText());
                }
            }
        });
        //生成类标签鼠标监听器
        generateClassLB.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent mouseEvent) {
                super.mouseClicked(mouseEvent);
                cardLayout.next(generateClassP);
                if (generateClassLB.getText().equals(currentClass)
                        && !TextUtils.isEmpty(Config.getInstant().getEntityPackName())
                        && !Config.getInstant().getEntityPackName().equals("null")) {
                    generateClassLB.setText(Config.getInstant().getEntityPackName());
                    generateClassTF.setText(Config.getInstant().getEntityPackName());
                }
                generateClassTF.requestFocus(true);
            }

        });
    }

    private void initListener() {

        okButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (generateClassTF.isFocusOwner()) {
                    editTP.requestFocus(true);
                } else {
                    onOK();
                }
            }
        });
        generateClassP.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent keyEvent) {
                super.keyReleased(keyEvent);
                if (keyEvent.getKeyCode() == KeyEvent.VK_ENTER) {
                    editTP.requestFocus(true);
                }
            }
        });
        errorLB.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent mouseEvent) {
                super.mouseClicked(mouseEvent);
                if (errorInfo != null) {
                    NotificationCenter.sendNotification(errorInfo, NotificationType.ERROR);
                }
            }
        });
        cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                onCancel();
            }
        });
        contentPane2.registerKeyboardAction(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                onCancel();
            }
        }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
    }

    private void onOK() {
        this.setAlwaysOnTop(false);
        String jsonSTR = editTP.getText().trim();
        if(TextUtils.isEmpty(jsonSTR)){
            NotificationCenter.sendNotificationForProject("请输入对象ToString的字符串",NotificationType.ERROR,project);
        }
        try {
            String json = ToStringUtils.toJSONString(jsonSTR);
            //格式化json
            commentAR.setText(format(json));
        }catch (Exception e){
            e.printStackTrace();
            NotificationCenter.sendNotificationForProject("toString转Json失败",NotificationType.ERROR,project);
        }
    }

    private void onCancel() {
        dispose();
    }

    public PsiClass getClss() {
        return cls;
    }

    public void setClass(PsiClass mClass) {
        this.cls = mClass;
    }

    public void setProject(Project mProject) {
        this.project = mProject;
    }

    public void setFile(PsiFile mFile) {
        this.file = mFile;
    }

    private void createUIComponents() {

    }

    /**
     * 显示设置弹框
     */
    public void openSettingDialog() {

        SettingDialog settingDialog = new SettingDialog(project);
        settingDialog.setSize(900, 720);
        settingDialog.setLocationRelativeTo(null);
//        settingDialog.setResizable(false);
        settingDialog.setVisible(true);
    }

    @Override
    public void cleanErrorInfo() {
        errorInfo = null;
    }

    @Override
    public void setErrorInfo(String error) {
        errorInfo = error;
    }

    @Override
    public void showError(ConvertBridge.Error err) {
        switch (err) {
            case DATA_ERROR:
                errorLB.setText("data err !!");
                if (Config.getInstant().isToastError()) {
                    Toast.make(project, errorLB, MessageType.ERROR, "click to see details");
                }
                break;
            case PARSE_ERROR:
                errorLB.setText("parse err !!");
                if (Config.getInstant().isToastError()) {
                    Toast.make(project, errorLB, MessageType.ERROR, "click to see details");
                }
                break;
            case PATH_ERROR:
                Toast.make(project, generateClassP, MessageType.ERROR, "the path is not allowed");
                break;
            default:
                break;
        }
    }

    /**
     * 格式化
     * @author 602595
     * @date: 2023/2/11 11:20
     * @return java.lang.String
     */
    public String format(String json) {
        json = json.trim();
        String formatJson = Constants.EMPTY;
        try {
            if (json.startsWith("{")) {
                JSONObject jsonObject = new JSONObject(json);
                formatJson = jsonObject.toString(4);
            } else if (json.startsWith("[")) {
                JSONArray jsonArray = new JSONArray(json);
                formatJson = jsonArray.toString(4);
            }
        } catch (JSONException jsonException) {
            try {
                String goodJson = JsonUtils.removeComment(json);
                formatJson = JsonUtils.formatJson(goodJson);
            } catch (Exception exception) {
                exception.printStackTrace();
                NotificationCenter.sendNotificationForProject("json格式不正确，格式需要标准的json或者json5",NotificationType.ERROR,project);
            }
        }
        return formatJson;

    }

}
